package com.wei.czz.framework.rabbitMQ.listener.dept;

import com.wei.czz.common.constant.EntityConstant;
import com.wei.czz.common.enums.CommonEnum;
import com.wei.czz.common.enums.admin.userRole.RelationModeEnum;
import com.wei.czz.common.enums.rabbitMQ.MqEnum;
import com.wei.czz.common.utils.CacheKeyUtils;
import com.wei.czz.framework.admin.entity.DeptEntity;
import com.wei.czz.framework.admin.entity.DeptRoleEntity;
import com.wei.czz.framework.admin.entity.DeptUserEntity;
import com.wei.czz.framework.admin.entity.UserRoleEntity;
import com.wei.czz.framework.admin.service.*;
import com.wei.czz.framework.common.service.TransactionService;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wyw
 * date: 2024-12-16 16:44:25
 * className: DeptUserQueueListener
 * version: 1.0
 * description:
 */
@Component
@AllArgsConstructor
public class DeptUserQueueListener {

    private static final Logger log = LoggerFactory.getLogger(DeptUserQueueListener.class);

    private final DeptService deptService;

    private final DeptUserService deptUserService;

    private final DeptRoleService deptRoleService;

    private final UserRoleService userRoleService;

    private final TransactionService transactionService;
    private final RedissonClient redissonClient;

    /**
     * 部门关联用户变化消息监听方法
     */
    @RabbitListener(queues = { MqEnum.Queue.DEPT_USER })
    public void deptUserMessage(List<Long> userIdList) {
        log.info("开始部门关联用户消息处理。userIdList={}", userIdList);

        String lockKey = CacheKeyUtils.getMqMessageLockKey(EntityConstant.DEPT_ROLE, MqEnum.Queue.DEPT_USER);

        RLock lock = redissonClient.getLock(lockKey);
        // 加锁1分钟
        lock.lock(1, TimeUnit.MINUTES);

        try {

            this.handler(userIdList);

        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }

        log.info("部门关联用户消息处理结束");
    }

    /**
     * 部门关联用户消息处理
     * @param userIdList 用户主键列表
     */
    private void handler(List<Long> userIdList) {
        Date date = new Date();

        /*
            获取部门用户
         */
        List<DeptUserEntity> deptUserList = deptUserService.findList(null, userIdList);
        if (deptUserList.isEmpty()) {
            log.warn("【部门关联用户消息处理】获取部门用户结果为空");
            return;
        }
        // 构造映射
        Map<Long, List<Long>> userDeptMap = new HashMap<>();
        Map<Long, List<Long>> deptUserMap = new HashMap<>();
        for (DeptUserEntity deptUser : deptUserList) {
            List<Long> deptIdList = userDeptMap.computeIfAbsent(deptUser.getUserId(), k -> new ArrayList<>());
            deptIdList.add(deptUser.getDeptId());

            List<Long> _userIdList = deptUserMap.computeIfAbsent(deptUser.getDeptId(), k -> new ArrayList<>());
            _userIdList.add(deptUser.getUserId());
        }
        List<Long> deptIdList = new ArrayList<>(deptUserMap.keySet());

        /*
            获取部门列表
         */
        List<DeptEntity> deptList = deptService.getList(deptIdList);
        if (deptList.isEmpty()) {
            log.warn("【部门关联用户消息处理】部门不存在");
            return;
        }

        // 构造映射
        Set<Long> deptIdSet = new HashSet<>();
        Map<Long, Set<Long>> userParentDeptMap = new HashMap<>();
        for (DeptEntity dept : deptList) {
            /*
                获取父级部门主键
             */
            deptIdList = deptService.findParentIdList(dept);
            for (Long deptId : deptIdList) {
                // 记录部门主键，为下面查询部门关联角色使用
                deptIdSet.add(deptId);

                // 获取部门关联用户
                List<Long> _userIdList = deptUserMap.getOrDefault(dept.getId(), Collections.emptyList());
                for (Long userId : _userIdList) {
                    userParentDeptMap.computeIfAbsent(userId, k -> new HashSet<>()).add(deptId);
                }
            }
        }

        /*
            获取部门角色
         */
        deptIdList = new ArrayList<>(deptIdSet);
        List<DeptRoleEntity> deptRoleList = deptRoleService.findList(deptIdList, null);
        if (deptRoleList.isEmpty()) {
            log.info("【部门关联用户消息处理】部门关联角色为空");
            return;
        }
        Map<Long, List<DeptRoleEntity>> deptRoleMap = deptRoleList.stream()
                .filter(deptRole -> CommonEnum.ZERO.getValue().equals(deptRole.getStatus()))
                .collect(Collectors.groupingBy(DeptRoleEntity::getDeptId));

        /*
            获取用户关联角色（通过部门关联角色）
         */
        List<UserRoleEntity> userRoleList = userRoleService.findUserRoleList(userIdList, null,
                Collections.singletonList(RelationModeEnum.DEPT_ROLE.getValue()));

        List<UserRoleEntity> saveUserRoleList = new ArrayList<>();
        List<UserRoleEntity> updateUserRoleList = new ArrayList<>();
        Map<Long, Set<Long>> userRoleMap = new HashMap<>();

        for (UserRoleEntity userRole : userRoleList) {
            // 记录用户关联角色
            userRoleMap.computeIfAbsent(userRole.getUserId(), k -> new HashSet<>()).add(userRole.getRoleId());

            // 获取用户关联部门
            deptIdList = userDeptMap.get(userRole.getUserId());
            if (Objects.isNull(deptIdList)) {
                log.warn("【部门关联用户消息处理】用户关联部门为空。userId={}", userRole.getUserId());
                continue;
            }
            boolean bool = false;
            for (Long deptId : deptIdList) {
                if (bool) {
                    break;
                }
                List<DeptRoleEntity> _deptRoleList = deptRoleMap.getOrDefault(deptId, Collections.emptyList());
                bool = _deptRoleList.stream().anyMatch(deptRole -> deptRole.getRoleId().equals(userRole.getRoleId()));
            }
            if (!bool) {
                deptIdSet = userParentDeptMap.getOrDefault(userRole.getUserId(), Collections.emptySet());
                for (Long deptId : deptIdSet) {
                    if (bool) {
                        break;
                    }
                    List<DeptRoleEntity> _deptRoleList = deptRoleMap.getOrDefault(deptId, Collections.emptyList());
                    bool = _deptRoleList.stream()
                            .filter(deptRole -> CommonEnum.ONE.getValue().equals(deptRole.getUseRange()))
                            .anyMatch(deptRole -> deptRole.getRoleId().equals(userRole.getRoleId()));
                }
            }
            if (!bool) {
                UserRoleEntity updateUserRole = new UserRoleEntity();
                updateUserRole.setId(userRole.getId())
                        .setDeleteStatus(CommonEnum.ONE.getValue())
                        .setUpdateTime(date)
                        .setUpdateUser(StringUtils.EMPTY)
                        .setUpdateUserId(CommonEnum.ZERO.getLongValue());
                updateUserRoleList.add(updateUserRole);
            }
        }

        for (Long userId : userIdList) {
            // 获取用户关联部门
            deptIdList = userDeptMap.get(userId);
            if (Objects.isNull(deptIdList)) {
                log.warn("【部门关联用户消息处理】用户关联部门为空。userId={}", userId);
                continue;
            }
            // 获取用户关联角色
            Set<Long> roleIdSet = userRoleMap.getOrDefault(userId, Collections.emptySet());

            for (Long deptId : deptIdSet) {
                deptRoleList = deptRoleMap.getOrDefault(deptId, Collections.emptyList());
                for (DeptRoleEntity deptRole : deptRoleList) {
                    if (roleIdSet.contains(deptRole.getRoleId())) {
                        continue;
                    }
                    // 记录新关联角色
                    roleIdSet.add(deptRole.getRoleId());

                    UserRoleEntity saveUserRole = new UserRoleEntity();
                    saveUserRole.setUserId(userId)
                            .setRoleId(deptRole.getRoleId())
                            .setRelationMode(RelationModeEnum.DEPT_ROLE.getValue())
                            .setDeleteStatus(CommonEnum.ZERO.getValue())
                            .setUpdateTime(date)
                            .setUpdateUser(StringUtils.EMPTY)
                            .setUpdateUserId(CommonEnum.ZERO.getLongValue())
                            .setCreateTime(date)
                            .setCreateUser(StringUtils.EMPTY)
                            .setCreateUserId(CommonEnum.ZERO.getLongValue());
                    saveUserRoleList.add(saveUserRole);
                }
            }

            // 获取用户关联部门的所有父级部门
            deptIdSet = userParentDeptMap.getOrDefault(userId, Collections.emptySet());
            for (Long deptId : deptIdSet) {
                deptRoleList = deptRoleMap.getOrDefault(deptId, Collections.emptyList());
                for (DeptRoleEntity deptRole : deptRoleList) {
                    if (roleIdSet.contains(deptRole.getRoleId())) {
                        continue;
                    }
                    if (!CommonEnum.ONE.getValue().equals(deptRole.getUseRange())) {
                        continue;
                    }
                    // 记录新关联角色
                    roleIdSet.add(deptRole.getRoleId());

                    UserRoleEntity saveUserRole = new UserRoleEntity();
                    saveUserRole.setUserId(userId)
                            .setRoleId(deptRole.getRoleId())
                            .setRelationMode(RelationModeEnum.DEPT_ROLE.getValue())
                            .setDeleteStatus(CommonEnum.ZERO.getValue())
                            .setUpdateTime(date)
                            .setUpdateUser(StringUtils.EMPTY)
                            .setUpdateUserId(CommonEnum.ZERO.getLongValue())
                            .setCreateTime(date)
                            .setCreateUser(StringUtils.EMPTY)
                            .setCreateUserId(CommonEnum.ZERO.getLongValue());
                    saveUserRoleList.add(saveUserRole);
                }
            }
        }

        transactionService.execute(() -> {
            if (!saveUserRoleList.isEmpty()) {
                userRoleService.batchSave(saveUserRoleList);
            }

            if (!updateUserRoleList.isEmpty()) {
                userRoleService.batchUpdate(updateUserRoleList);
            }
        });
    }
}
